package logic

import (
	"api/service"
	"api/service/cert"
	"context"
	"fmt"
	"github.com/go-pay/gopay"
	"github.com/go-pay/gopay/wechat/v3"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
	"strconv"
	"time"

	"api/internal/svc"
	"api/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type WxCreateOrderLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewWxCreateOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WxCreateOrderLogic {
	return &WxCreateOrderLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

// 微信创单
func (l *WxCreateOrderLogic) WxCreateOrder(req *types.RequestCreateOrder) (resp *types.ResponseWxOrder, err error) {
	client, err := wechat.NewClientV3(cert.WxMchid, cert.WxSerialNo, cert.WxApiV3Key, cert.WxPrivateKey)

	if err != nil {
		l.Error("微信支付客户端实例化失败:", err)
		resp.Code = 500
		return resp, nil
	}

	// 启用自动同步返回验签，并定时更新微信平台API证书（开启自动验签时，无需单独设置微信平台API证书和序列号）
	err = client.AutoVerifySign()
	if err != nil {
		l.Error("微信支付客户端自动验签失败:", err)
		fmt.Println(err.Error())
		resp.Code = 500
		return resp, nil
	}

	// 生成订单号
	tradeNo := service.GenerateUniqueID(32)
	expire := time.Now().Add(10 * time.Minute).Format(time.RFC3339)

	// 固定标题
	description := "用户到店付款"

	num, err := strconv.ParseFloat(req.Amount, 64) // 订单金额单位为分 前端传来是角
	num = num * 100
	bm := make(gopay.BodyMap)
	bm.Set("sp_appid", l.svcCtx.Config.WxApp.Appid).
		Set("sp_mchid", cert.WxMchid).
		Set("sub_mchid", strconv.Itoa(req.Code)).
		Set("description", description).
		Set("out_trade_no", tradeNo).
		Set("time_expire", expire).
		Set("notify_url", cert.WxNotifyUrl).
		SetBodyMap("amount", func(bm gopay.BodyMap) {
			bm.Set("total", num).Set("currency", "CNY")
		}).
		SetBodyMap("payer", func(bm gopay.BodyMap) {
			bm.Set("sp_openid", req.OpenId)
		})

	wxRsp, err := client.V3PartnerTransactionJsapi(l.ctx, bm)
	if err != nil {
		l.Error("微信支付预支付下单失败:", err)
		fmt.Println(err.Error())
		resp.Code = 500
		return resp, nil
	}
	if wxRsp.Code == 200 {

		// 创建单号
		conn := sqlx.NewMysql(l.svcCtx.Config.DataSource)
		orderService := service.NewOrderService(l.ctx, l.svcCtx)

		discountNum, err := strconv.ParseFloat(req.Discount, 64) // 订单金额单位为分 前端传来是角
		discountNum = discountNum * 100

		err = orderService.CreateOrder(conn, int(num), req.Code, tradeNo, wxRsp.Response.PrepayId,
			service.TYPE_WX, req.CreateType, req.DiscountId, req.OpenId, int(discountNum), req.Table)
		if err != nil {
			fmt.Println(err.Error())
			resp.Code = 500
			return resp, nil
		}

		// 预下单成功
		resp.Code = 200
		resp.PrepayId = wxRsp.Response.PrepayId

		// 生成支付参数
		applet, _ := client.PaySignOfApplet(cert.WxAppId, wxRsp.Response.PrepayId)
		resp.Timestamp = applet.TimeStamp
		resp.NonceStr = applet.NonceStr
		resp.Package = applet.Package
		resp.SignType = applet.SignType
		resp.PaySign = applet.PaySign

		return resp, nil
	}
	l.Error("支付失败:订单号:"+tradeNo, wxRsp.Error)
	resp.Code = 500
	return resp, nil
}
